package ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import entity.EntityConstants;
import entity.Event;
import entity.RecurrenceRule;
import entity.ExDate;

/**
 * A Panel that contains the options to create and add
 * Events to the currently selected Calendar.
 * 
 * @author Sean Young, Elliot Ito
 * @version 1.0
 *
 */
public class CreateEventPanel extends JPanel implements EntityConstants{
	private JPanel eventSummary, classification, priority, buttonPanel, rrulePanel, exPanel;
	private JTextField eventSummaryText;
	private RecurrenceRule rrule;
	private DateStartEndPanel dateStartEndPanel;
	private GPSPanel gps;
	private JRadioButton levelPublic, levelPrivate, levelConfidential;
	private JComboBox prioLevel;
	private JButton addEvent, discardEvent, repeat, repeatExceptions;
	private EventPanelListener listener;
	private CalendarUI parent;
	private ExDate exDate;
	private MonthlyExPanel montlyExPanel;
	
	/**
	 * Constructor for the CreateEventPanel. Requires a reference
	 * to the main panel of the CalendarUI.
	 * @param parent The main panel
	 */
	public CreateEventPanel(CalendarUI parent) {
		super();
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		
		this.parent = parent;
		
		listener = new EventPanelListener();
		eventSummary = new JPanel(new FlowLayout(FlowLayout.LEFT));
		eventSummaryText = new JTextField(50);
		eventSummaryText.setText("Untitled Event");
		eventSummary.add(eventSummaryText);
		add(eventSummary);
		
		dateStartEndPanel = new DateStartEndPanel();
		add(dateStartEndPanel);
		
		rrulePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		repeat = new JButton("Repeat");
		repeat.setActionCommand("repeat");
		repeat.addActionListener(listener);
		rrulePanel.add(repeat);
		repeatExceptions = new JButton("Repeat Exceptions");
		repeatExceptions.setActionCommand("repeatExceptions");
		repeatExceptions.addActionListener(listener);
		rrulePanel.add(repeatExceptions);
		add(rrulePanel);
		
		
		classification = new JPanel(new FlowLayout(FlowLayout.LEFT));
		ButtonGroup classButtons = new ButtonGroup();
		
		levelPublic = new JRadioButton("Public");
		levelPublic.setSelected(true);
		
		levelPrivate = new JRadioButton("Private");
		
		levelConfidential = new JRadioButton("Confidential");
		
		classButtons.add(levelPublic);
		classButtons.add(levelPrivate);
		classButtons.add(levelConfidential);
		classification.add(levelPublic);
		classification.add(levelPrivate);
		classification.add(levelConfidential);
		add(classification);
		
		priority = new JPanel(new FlowLayout(FlowLayout.LEFT));
		String[] levels = {"Highest", "High", "Normal", "Low", "Lowest"};
		prioLevel = new JComboBox<String>(levels);
		prioLevel.setSelectedIndex(2);
		priority.add(new JLabel("Priority"));
		priority.add(prioLevel);
		add(priority);
		
		gps = new GPSPanel();
		add(gps);
		
		buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		addEvent = new JButton("Add Event");
		discardEvent = new JButton("Discard");
		discardEvent.setActionCommand("discard");
		discardEvent.addActionListener(listener);
		
		addEvent.setActionCommand("addEvent");
		addEvent.addActionListener(listener);
		buttonPanel.add(addEvent);
		buttonPanel.add(discardEvent);
		add(buttonPanel);
	}
	
	/**
	 * Adds a recurrence rule to the Event.
	 * @param rrule A recurrence rule to add.
	 */
	public void addRRule(RecurrenceRule rrule) {
		this.rrule = rrule;
	}
	
	/**
	 * Generates a panel where a user can generate
	 * recurrence rule.
	 */
	public void showRRuleWindow() {
		RRulePanel.showRRuleWindow(this);
	}
	
	/***
	 * Adds an exception date to the Event
	 * @param date An exception date/s to add.
	 */
	public void addExPanel(ExDate date){
		this.exDate = date;
	}
	
	/**
	 * Generates a panel where a user can generate
	 * exception dates.
	 */
	public void showExPanel(){
		MonthlyExPanel.showExPanelWindow(this);
	}
	
	/**
	 * Resets the CreateEvent panel.
	 */
	public void reset() {
		eventSummaryText.setText("Untitled Event");
		levelPublic.setSelected(true);
		prioLevel.setSelectedIndex(2);
		gps.reset();
		dateStartEndPanel.reset();
		rrule = null;
		exPanel = null;
		
	}
	
	/**
	 * Returns the start date specified in the DateStartEnd
	 * Panel. For use in determining valid end dates for 
	 * recurrence rules.
	 * @return The start date of the event
	 */
	public Date getStartDate() {
		return dateStartEndPanel.returnStartDate();
	}
	
	/**
	 * Returns the whether the start date specified in the 
	 * DateStartEndPanel is valid. For use in determining 
	 * valid end dates for recurrence rules.
	 * @return The validity of the start date
	 */
	public boolean hasValidStartDate() {
		return dateStartEndPanel.hasValidStartDate();
	}
	
	/**
	 * Builds an Event Object using data from the fields of 
	 * the CreateEventPanel. The method will return null
	 * in the case of an invalid required field.
	 * @return The created Event object 
	 */
	public Event buildEvent() {
		Event currentEvent = new Event();
		currentEvent.addSummary(eventSummaryText.getText());
		if(dateStartEndPanel.hasValidDates()) {
			currentEvent.addDateTimeStart(dateStartEndPanel.returnStartDate());
			currentEvent.addDateTimeEnd(dateStartEndPanel.returnEndDate());
		} else {
			JOptionPane.showMessageDialog(this, "Event not added.\nInvalid Start and/or End Date");
			return null;
		}
		if(levelPublic.isSelected()) {
			currentEvent.addClass(PUBLIC);
		} else if(levelPrivate.isSelected()) {
			currentEvent.addClass(PRIVATE);
		} else if(levelConfidential.isSelected()) {
			currentEvent.addClass(CONFIDENTIAL);
		}
		
		if(rrule != null) {
			currentEvent.addRecurrenceRule(rrule);
			currentEvent.addException(exDate);
		}
		
		switch((String)prioLevel.getSelectedItem()) {
		case "Highest": currentEvent.addPriority(1);break;
		case "High": currentEvent.addPriority(2);break;
		case "Normal": currentEvent.addPriority(3);break;
		case "Low": currentEvent.addPriority(4);break;
		case "Lowest": currentEvent.addPriority(5);break;
		default: currentEvent.addPriority(0);
		}
		
		if(rrule.toString().contains("UNTIL") || rrule.toString().contains("COUNT")){
			int start = dateStartEndPanel.returnStartYear();
			int end = dateStartEndPanel.returnEndYear();
			ArrayList<String> year = new ArrayList<String>();
			for(int x = start; x <= end; x++){
				year.add(Integer.toString(x));
			}
			exDate.addMonthException(year);
		}
			
		
		if(!gps.isEmpty()) {
			if (gps.hasValidCoordinates()) {
				currentEvent.addGeoPos(gps.getLatitude(), gps.getLongitude());
			} else {
				System.out.println(gps.hasValidCoordinates());
				JOptionPane.showMessageDialog(this, "Event not added.\nInvalid or Missing GPS Coordinates.");
				return null;
			}
		}
		JOptionPane.showMessageDialog(this, "Event added.");
		return currentEvent;
	}
	
	/**
	 * Listener that performs specific actions based upon the 
	 * button pressed.
	 */
	public class EventPanelListener implements ActionListener{
		
		@Override
		public void actionPerformed(ActionEvent e) {
			
			Event event = new Event();
			
			switch(e.getActionCommand()){
				case "addEvent" :  event = buildEvent();
								   if(event != null) {
									   parent.addEvent(event);
									   reset();
								   } 
								   break;
								   
				case "discard" :   reset();
								   break;
				case "repeat"  :  showRRuleWindow();
				 								  break;
				case "repeatExceptions" : showExPanel();
										  
			}
		}	
	}
}
